package com.hualala.supplychain.methodext;


import com.hualala.supplychain.methodext.annotation.DoMethodExtAll;
import com.hualala.supplychain.methodext.constans.MethodEnum;
import com.hualala.supplychain.methodext.service.DoMethodExtAllService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * @author lz
 * @DATE 2022/5/31 15:42
 */
@Aspect
@Component
@Slf4j
public class DoMethodExtAllPoint {

    @Autowired
    private ApplicationContext applicationContext;


    /**
     * 切点
     */
    @Pointcut("@annotation(com.hualala.supplychain.methodext.annotation.DoMethodExtAll)")
    public void servicePointcut() {
    }


    /**
     * 切点方法执行前运行
     *
     * @param joinPoint
     */
    @Before(value = "servicePointcut() && @annotation(methodExtAll)")
    public void doBefore(JoinPoint joinPoint, DoMethodExtAll methodExtAll) {
        doEvent(joinPoint, MethodEnum.BEFOR, methodExtAll,  null);
    }


    /**
     * 切点方法执行后运行，不管切点方法执行成功还是出现异常
     *
     * @param joinPoint
     */
    @After(value = "servicePointcut()  && @annotation(methodExtAll)")
    public void doAfter(JoinPoint joinPoint, DoMethodExtAll methodExtAll) {
        doEvent(joinPoint, MethodEnum.AFTER, methodExtAll,  null);
    }


    /**
     * 切点方法成功执行返回后运行
     *
     * @param joinPoint
     * @param returnValue
     */
    @AfterReturning(value = "servicePointcut()  && @annotation(methodExtAll)", returning = "returnValue")
    public void doAfterReturning(JoinPoint joinPoint, DoMethodExtAll methodExtAll, Object returnValue) {
        doEvent(joinPoint, MethodEnum.AFTER_RETURNING, methodExtAll, null);
    }


    /**
     * 适配要进入的实现类
     *
     * @param joinPoint
     * @param action
     * @param returnValue
     */
    private void doEvent(JoinPoint joinPoint, MethodEnum action,DoMethodExtAll methodExtAll, Object returnValue) {
        String interfaceName = joinPoint.getTarget().getClass().getSimpleName();
        Object[] args = joinPoint.getArgs();
        //获取要执行的子类的名称
        String className = methodExtAll.className();
        //获取需要执行的拦截方法
        MethodEnum[] types = methodExtAll.type();
        List<MethodEnum> methodEnums = Arrays.asList(types);
        //获取接口的所有子类
        Map<String, DoMethodExtAllService> beansOfType = applicationContext.getBeansOfType(DoMethodExtAllService.class);
        //循环获取TrailService接口所有的实现类
        for (DoMethodExtAllService handle : beansOfType.values()) {
            //这里判断的是全路径名称
            if (handle.getClass().getSimpleName().equals(className)) {
                if (action.equals(MethodEnum.BEFOR) && methodEnums.contains(MethodEnum.BEFOR)) {
                    handle.doBefor(interfaceName,args);
                } else if (action.equals(MethodEnum.AFTER) && methodEnums.contains(MethodEnum.AFTER)) {
                    handle.doAfter(interfaceName,args);
                } else if (action.equals(MethodEnum.AFTER_RETURNING) && methodEnums.contains(MethodEnum.AFTER_RETURNING)) {
                    handle.doAfterReturning(interfaceName,args, returnValue);
                }
            }
        }
    }
}
